package jinyilw.swing.visuals.Jcomp;

import jinyilw.swing.graphics.GraphicsTools;
import jinyilw.swing.graphics.RenderingConfig;
import jinyilw.swing.i18n.ICSetting;
import jinyilw.swing.rlaf.UITools;
import jinyilw.swing.rlaf.theme.RThemeColor;
import jinyilw.swing.rlaf.utils.RBorderFactory;

import javax.swing.border.Border;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;

public class TransButton extends JImageTextComp // 透明响应式面板
{
	private static final long serialVersionUID = -2979195365146419534L;
	private final RoundBorder roundBorder = new RoundBorder();

	public TransButton()
	{
		initGUI();
	}

	public TransButton(String text)
	{
		super(text);
		initGUI();
	}

	public TransButton(ICSetting iSetting)
	{
		setText(iSetting);
		initGUI();
	}

	private void initGUI()
	{
		enableMouseAct();
		setBorder(roundBorder);
	}

	public void setBorderActivated(boolean activated)
	{
		roundBorder.setActivated(activated);
	}

	ActionEvent getActionEvent(MouseEvent e)
	{
		return new ActionEvent(TransButton.this, e.getID(),
				getName());
	}

	public void addActionListener(ActionListener listener)
	{
		if (listener != null)
			addClickOperator(e -> listener.actionPerformed(getActionEvent((MouseEvent) e)));
	}

	@Override
	public void paint(Graphics g)
	{
		boolean isEnabled = isEnabled();
		roundBorder.setActivated(isEnabled && isRollover);
		Graphics2D g2d = (Graphics2D) g;
		if (isEnabled && isPressed)
			g2d.translate(0.5, 0.5);
		super.paint(g);
		if (isEnabled && isPressed)
			g2d.translate(-0.5, -0.5);
	}

	private static class RoundBorder implements Border
	{
		private int arc = RBorderFactory.defaultArc;
		private int innerSpace = 4;
		private int shadowSize = 2;
		private final Color shadowColor = Color.black;
		private final int shadowOpacity = 96;
		private Color[] shadowColors;
		private final Color hiColor = new Color(255, 255, 255, 220);
		private final Color loColor = new Color(130, 130, 130, 220);
		private Insets borderInsets = null;
		private boolean activated;
		private final RenderingConfig renderingConfig = new RenderingConfig();

		public RoundBorder()
		{
			borderInsets = new Insets(innerSpace, innerSpace,
					innerSpace + shadowSize, innerSpace + shadowSize);
			initShadow(shadowSize);
		}

		public RoundBorder(int arc)
		{
			this.arc = arc;
			borderInsets = new Insets(innerSpace, innerSpace,
					innerSpace + shadowSize, innerSpace + shadowSize);
			initShadow(shadowSize);
		}

		public RoundBorder(int arc, boolean activated)
		{
			this(arc);
			this.activated = activated;
		}

		public RoundBorder(int innerSpace, int arc)
		{
			this(innerSpace, arc, 3);
		}

		public RoundBorder(int innerSpace, int arc, int shadowSize)
		{
			if (innerSpace < 2)
				innerSpace = 2;
			this.innerSpace = innerSpace;
			this.arc = arc;
			this.shadowSize = shadowSize;
			if (shadowSize > 0)
				initShadow(shadowSize);
			borderInsets = new Insets(innerSpace, innerSpace,
					innerSpace + shadowSize, innerSpace + shadowSize);
		}

		public void setShadowSize(int shadowSize)
		{
			if (shadowSize < 0 || this.shadowSize == shadowSize)
				return;
			this.shadowSize = shadowSize;
			if (shadowSize > 0)
				initShadow(shadowSize);
		}

		private void initShadow(int shadowSize)
		{
			shadowColors = new Color[shadowSize];
			int opacity = shadowOpacity;
			int r = shadowColor.getRed();
			int g = shadowColor.getGreen();
			int b = shadowColor.getBlue();
			for (int i = 0; i < shadowSize; i++)
			{
				shadowColors[i] = new Color(r, g, b, opacity);
				opacity = opacity / 2;
			}
		}

		public void setActivated(boolean activated)
		{
			this.activated = activated;
		}

		public boolean isActivated()
		{
			return activated;
		}

		@Override
		public void paintBorder(Component c, Graphics g, int x, int y, int w,
				int h)
		{
			Graphics2D g2d = (Graphics2D) g;
			renderingConfig.setAAPainting(g2d);
			if (shadowSize > 0)
			{
				int cc = arc / 2 + 4;
				int xx = x + cc, yy = y + cc;
				int ww = w - shadowSize - cc, hh = h - shadowSize - cc;
				int rr = arc + 2;
				for (int i = 0; i < shadowSize; i++)
				{
					g2d.setColor(shadowColors[i]);
					GraphicsTools.drawBottomRightRoundRect(g2d, xx, yy, ww + i,
							hh + i, rr);
				}
			}
			if (UITools.isLight())
			{
				g2d.setColor(loColor);
				g2d.drawRoundRect(x, y, w - shadowSize - 1, h - shadowSize - 1,
						arc + 3, arc + 3);
				g2d.setColor(activated ? RThemeColor.themeColor : hiColor);
			} else
			{
				g2d.setColor(activated
						? RThemeColor.themeColor
						: RThemeColor.colorSet.borderColor);
			}
			Stroke saveStroke = g2d.getStroke();
			g2d.setStroke(GraphicsTools.getLargeStroke());
			g2d.drawRoundRect(x + 1, y + 1, w - shadowSize - 3,
					h - shadowSize - 3, arc, arc);
			g2d.setStroke(saveStroke);
			renderingConfig.resetAAPainting(g2d);
		}

		@Override
		public Insets getBorderInsets(Component c)
		{
			if (borderInsets != null)
				return borderInsets;
			return new Insets(0, 0, 0, 0);
		}

		@Override
		public boolean isBorderOpaque()
		{
			return false;
		}
	}
}
